package belf.migrate.engine.ddl.trigger.oracle;

import belf.migrate.api.model.QualifiersModel;
import belf.migrate.api.table.schema.Catalog;
import belf.migrate.engine.ddl.BaseDDLConvert;
import belf.migrate.plugin.oracle.antlr.PlSqlLexer;
import belf.migrate.plugin.oracle.antlr.PlSqlParser;
import belf.migrate.plugin.oracle.antlr.PlSqlParserBaseListener;
import com.github.vertical_blank.sqlformatter.SqlFormatter;
import com.github.vertical_blank.sqlformatter.languages.Dialect;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.util.Arrays;
import java.util.List;

/**
 * Oracle触发器转金仓，和转达梦一样的方式
 */
public class Oracle2KingbaseTriggerConvert extends BaseDDLConvert {

    public Oracle2KingbaseTriggerConvert(String objectName, String sql, Catalog sourceCatalog, Catalog sinkCatalog,
                                         String schema, QualifiersModel qualifiersModel) {
        super(objectName, sql, sourceCatalog, sinkCatalog, schema, qualifiersModel);
    }

    /**
     * 主要修改表、视图名称，加上前缀schema
     * @return
     */
    @Override
    public String convert() {
        CharStream input = CharStreams.fromString(sql);

        // 创建词法分析器和解析器
        PlSqlLexer lexer = new PlSqlLexer(input);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        PlSqlParser parser = new PlSqlParser(tokens);

        // 从解析器中获取起始规则并进行解析
        PlSqlParser.Sql_scriptContext tree = parser.sql_script();
        ParseTreeWalker walker = new ParseTreeWalker();
        OracleTriggerListener listener = new OracleTriggerListener();
        walker.walk(listener, tree);

        return listener.getDdl();
    }

    private class OracleTriggerListener extends PlSqlParserBaseListener {
        List<String> symbols = Arrays.asList("'", "\"", ".", ",", "(", ")", "=", "<", ">");

        private StringBuilder sb = new StringBuilder();
        @Override
        public void visitTerminal(TerminalNode node) {
            String text = node.getText().trim();
            if ("<EOF>".equalsIgnoreCase(text)) {
                return;
            }

            ParseTree parentNode = getParent(PlSqlParser.Trigger_nameContext.class.getName(), node);
            // 1.给触发器名强制加上schema前缀
            if (null != parentNode && parentNode instanceof PlSqlParser.Trigger_nameContext) {
                String parentText = parentNode.getText();
                if (parentText.indexOf('.') < 0) {
                    sb.append(" " + schema + "." + node.getText());
                    return;
                }
            }

            // 2.给表、视图名称强制加上schema前缀
            parentNode = getParent(PlSqlParser.Tableview_nameContext.class.getName(), node);
            if (null != parentNode && parentNode instanceof PlSqlParser.Tableview_nameContext) {
                String parentText = parentNode.getText();
                if (parentText.indexOf('.') < 0) {
                    sb.append(" " + schema + "." + node.getText());
                    return;
                }
            }

            if (symbols.contains(node.getText())) { // 3.处理标点符号，标点符号后面不加空格
                sb.append(text);
            } else if(";".equals(text) ) {
                sb.append(text + "\n");
            } else {
                if (sb.length() > 1 && sb.charAt(sb.length() - 1) == '.') {//是标识符的后面部分，不要在前面加空格
                    sb.append(text);
                } else {
                    if (sb.length() > 0) {
                        sb.append(" ");
                    }
                    sb.append(" " + text);
                }
            }
        }

        public String getDdl() {
            return SqlFormatter.of(Dialect.PlSql).format(sb.toString());
        }
    }
}
